home *** CD-ROM | disk | FTP | other *** search
/ Aminet 1 / Aminet - June 1993 [Walnut Creek].iso / usenet / sources / volume90 / unix / make / part02 < prev   
Encoding:
Internet Message Format  |  1990-01-17  |  14.3 KB

  1. Path: xanth!cs.odu.edu!Amiga-Request
  2. From: Amiga-Request@cs.odu.edu (Amiga Sources/Binaries Moderator)
  3. Newsgroups: comp.sources.amiga
  4. Subject: v90i021: make - a re-implementation of the UNIX make utility, Part02/02
  5. Message-ID: <11028@xanth.cs.odu.edu>
  6. Date: 17 Jan 90 23:17:09 GMT
  7. Sender: tadguy@cs.odu.edu
  8. Reply-To: Olaf 'Rhialto' Seibert <U211344@HNYKUN11.BITNET>
  9. Lines: 617
  10. Approved: tadguy@cs.odu.edu (Tad Guy)
  11.  
  12. Submitted-by: Olaf 'Rhialto' Seibert <U211344@HNYKUN11.BITNET>
  13. Posting-number: Volume 90, Issue 021
  14. Archive-name: unix/make/part02
  15.  
  16. #!/bin/sh
  17. # This is a shell archive.  Remove anything before this line, then unpack
  18. # it by saving it into a file and typing "sh file".  To overwrite existing
  19. # files, type "sh file -c".  You can also feed this as standard input via
  20. # unshar, or by typing "sh <file", e.g..  If this archive is complete, you
  21. # will see the following message at the end:
  22. #        "End of archive 2 (of 2)."
  23. # Contents:  make.c
  24. # Wrapped by tadguy@xanth on Wed Jan 17 18:16:24 1990
  25. PATH=/bin:/usr/bin:/usr/ucb ; export PATH
  26. if test -f 'make.c' -a "${1}" != "-c" ; then 
  27.   echo shar: Will not clobber existing file \"'make.c'\"
  28. else
  29. echo shar: Extracting \"'make.c'\" \(11870 characters\)
  30. sed "s/^X//" >'make.c' <<'END_OF_FILE'
  31. X/*
  32. X *    Do the actual making for make
  33. X */
  34. X
  35. X#include <stdio.h>
  36. X#ifdef unix
  37. X#include <sys/types.h>
  38. X#include <sys/stat.h>
  39. X#include <sys/errno.h>
  40. X#endif
  41. X#ifdef eon
  42. X#include <sys/stat.h>
  43. X#include <sys/err.h>
  44. X#endif
  45. X#ifdef os9
  46. X#include <time.h>
  47. X#include <os9.h>
  48. X#include <modes.h>
  49. X#include <direct.h>
  50. X#include <errno.h>
  51. X#endif
  52. X#ifdef amiga
  53. X#include <ctype.h>
  54. X#include <errno.h>
  55. X#include <libraries/dosextens.h>
  56. X#include <exec/memory.h>
  57. X#include <exec/io.h>
  58. X#include <exec/ports.h>
  59. X#include <functions.h>
  60. X#undef TRUE            /*OIS*0.80*/
  61. X#undef FALSE            /*OIS*0.80*/
  62. X/*#define ACTION_SET_DATE     34L /*OIS*0.80*/
  63. X#endif
  64. X#include "h.h"
  65. X
  66. X
  67. X
  68. X/*
  69. X *    Exec a shell that returns exit status correctly (/bin/esh).
  70. X *    The standard EON shell returns the process number of the last
  71. X *    async command, used by the debugger (ugg).
  72. X *    [exec on eon is like a fork+exec on unix]
  73. X */
  74. Xint
  75. Xdosh(string, shell)
  76. X    char       *string;
  77. X    char       *shell;
  78. X{
  79. X    int         number;
  80. X
  81. X#ifdef amiga
  82. X    char       *av[3], *s, *p;
  83. X    int         i;
  84. X
  85. X    fflush(stdout); /*OIS*0.80*/
  86. X    if ((p = s = malloc((unsigned) strlen(string) + 1)) == NULL)
  87. X    fatal("No memory for command '%s'", string);
  88. X    strcpy(p, string);                  /* make a copy of the string */
  89. X    i = 0;
  90. X    av[0] = gettok(&p);                 /* get first argument */
  91. X    av[1] = p;                /* get rest of command line */
  92. X    av[2] = NULL;
  93. X    if (fexecv(av[0], av) == -1)
  94. X    fatal("couldn't execute command '%s', error return %02x\n",
  95. X          av[0], errno);
  96. X    number = wait();
  97. X    free(s);
  98. X    return number;
  99. X#endif
  100. X
  101. X#ifdef unix
  102. X    return system(string);
  103. X#endif
  104. X#ifdef eon
  105. X    return ((number = execl(shell, shell, "-c", string, 0)) == -1) ?
  106. X    -1 :            /* couldn't start the shell */
  107. X    wait(number);           /* return its exit status */
  108. X#endif
  109. X#ifdef os9
  110. X    int         status, pid;
  111. X
  112. X    strcat(string, "\n");
  113. X    if ((number = os9fork(shell, strlen(string), string, 0, 0, 0)) == -1)
  114. X    return -1;        /* Couldn't start a shell */
  115. X    do {
  116. X    if ((pid = wait(&status)) == -1)
  117. X        return -1;        /* child already died!?!? */
  118. X    } while (pid != number);
  119. X
  120. X    return status;
  121. X#endif
  122. X}
  123. X
  124. X
  125. X/*
  126. X *    Do commands to make a target
  127. X */
  128. Xvoid
  129. Xdocmds1(np, lp)
  130. X    struct name    *np;
  131. X    struct line    *lp;
  132. X{
  133. X    bool        ssilent;
  134. X    bool        signore;
  135. X    int         estat;
  136. X    register char  *q;
  137. X    register char  *p;
  138. X    char       *shell;
  139. X    register struct cmd *cp;
  140. X#ifdef amiga
  141. X    long SetSignal();
  142. X#endif
  143. X
  144. X#ifndef amiga
  145. X    if (*(shell = getmacro("SHELL")) == '\0')
  146. X#ifdef eon
  147. X    shell = ":bin/esh";
  148. X#endif
  149. X#ifdef unix
  150. X    shell = "/bin/sh";
  151. X#endif
  152. X#ifdef os9
  153. X    shell = "shell";
  154. X#endif
  155. X#else /* for amiga */
  156. X    shell = NULL;
  157. X#endif
  158. X
  159. X    for (cp = lp->l_cmd; cp; cp = cp->c_next) {
  160. X    strcpy(str1, cp->c_cmd);
  161. X    expand(str1);
  162. X    q = str1;
  163. X    ssilent = silent;
  164. X    signore = ignore;
  165. X    while ((*q == '@') || (*q == '-')) {
  166. X        if (*q == '@')      /* Specific silent  */
  167. X        ssilent = TRUE;
  168. X        else        /* Specific ignore  */
  169. X        signore = TRUE;
  170. X        q++;        /* Not part of the command  */
  171. X    }
  172. X
  173. X    if (!domake)
  174. X        ssilent = 0;
  175. X
  176. X    if (!ssilent)
  177. X        fputs("    ", stdout);
  178. X
  179. X    for (p = q; *p; p++) {
  180. X        if (*p == '\n' && p[1] != '\0') {
  181. X        *p = ' ';
  182. X        if (!ssilent)
  183. X            fputs("\\\n", stdout);
  184. X        } else if (!ssilent)
  185. X        putchar(*p);
  186. X    }
  187. X    if (!ssilent)
  188. X        putchar('\n');
  189. X
  190. X    if (domake) {           /* Get the shell to execute it  */
  191. X        if ((estat = dosh(q, shell)) != 0) {
  192. X        if (estat == -1)
  193. X            fatal("Couldn't execute %s", shell);
  194. X        else {
  195. X            printf("%s: Error code %d", myname, estat);
  196. X            if (signore)
  197. X            fputs(" (Ignored)\n", stdout);
  198. X            else {
  199. X            putchar('\n');
  200. X            if (!(np->n_flag & N_PREC))
  201. X                if (unlink(np->n_name) == 0)
  202. X                printf("%s: '%s' removed.\n", myname, np->n_name);
  203. X            exit(estat);
  204. X            }
  205. X        }
  206. X        }
  207. X#ifdef amiga
  208. X        if ((SetSignal(0L, SIGBREAKF_CTRL_D) & SIGBREAKF_CTRL_D) != 0) {
  209. X        fatal("Abort due to ^D");   /*OIS*0.80*/
  210. X        }
  211. X#endif
  212. X    }
  213. X    }
  214. X}
  215. X
  216. X
  217. Xdocmds(np)
  218. X    struct name    *np;
  219. X{
  220. X    register struct line *lp;
  221. X
  222. X
  223. X    for (lp = np->n_line; lp; lp = lp->l_next)
  224. X    docmds1(np, lp);
  225. X}
  226. X
  227. X
  228. X#ifdef os9
  229. X/*
  230. X *    Some stuffing around to get the modified time of a file
  231. X *    in an os9 file system
  232. X */
  233. Xgetmdate(fd, tbp)
  234. X    struct sgtbuf  *tbp;
  235. X{
  236. X    struct registers regs;
  237. X    static struct fildes fdbuf;
  238. X
  239. X
  240. X    regs.rg_a = fd;
  241. X    regs.rg_b = SS_FD;
  242. X    regs.rg_x = &fdbuf;
  243. X    regs.rg_y = sizeof(fdbuf);
  244. X
  245. X    if (_os9(I_GETSTT, ®s) == -1) {
  246. X    errno = regs.rg_b & 0xff;
  247. X    return -1;
  248. X    }
  249. X    if (tbp) {
  250. X    _strass(tbp, fdbuf.fd_date, sizeof(fdbuf.fd_date));
  251. X    tbp->t_second = 0;    /* Files are only acurate to mins */
  252. X    }
  253. X    return 0;
  254. X}
  255. X
  256. X
  257. X/*
  258. X *    Kludge routine to return an aproximation of how many
  259. X *    seconds since 1980.  Dates will be in order, but will not
  260. X *    be lineer
  261. X */
  262. Xtime_t
  263. Xcnvtime(tbp)
  264. X    struct sgtbuf  *tbp;
  265. X{
  266. X    long        acc;
  267. X
  268. X
  269. X    acc = tbp->t_year - 80;    /* Baseyear is 1980 */
  270. X    acc = acc * 12 + tbp->t_month;
  271. X    acc = acc * 31 + tbp->t_day;
  272. X    acc = acc * 24 + tbp->t_hour;
  273. X    acc = acc * 60 + tbp->t_minute;
  274. X    acc = acc * 60 + tbp->t_second;
  275. X
  276. X    return acc;
  277. X}
  278. X
  279. X
  280. X/*
  281. X *    Get the current time in the internal format
  282. X */
  283. Xtime(tp)
  284. X    time_t       *tp;
  285. X{
  286. X    struct sgtbuf   tbuf;
  287. X
  288. X
  289. X    if (getime(&tbuf) < 0)
  290. X    return -1;
  291. X
  292. X    if (tp)
  293. X    *tp = cnvtime(&tbuf);
  294. X
  295. X    return 0;
  296. X}
  297. X#endif
  298. X
  299. X
  300. X/*
  301. X *    Get the modification time of a file.  If the first
  302. X *    doesn't exist, it's modtime is set to 0.
  303. X */
  304. Xvoid
  305. Xmodtime(np)
  306. X    struct name    *np;
  307. X{
  308. X#ifdef unix
  309. X    struct stat     info;
  310. X    int         fd;
  311. X
  312. X
  313. X    if (stat(np->n_name, &info) < 0) {
  314. X    if (errno != ENOENT)
  315. X        fatal("Can't open %s; error %d", np->n_name, errno);
  316. X
  317. X    np->n_time = 0L;
  318. X    } else
  319. X    np->n_time = info.st_mtime;
  320. X#endif
  321. X#ifdef eon
  322. X    struct stat     info;
  323. X    int         fd;
  324. X
  325. X
  326. X    if ((fd = open(np->n_name, 0)) < 0) {
  327. X    if (errno != ER_NOTF)
  328. X        fatal("Can't open %s; error %02x", np->n_name, errno);
  329. X
  330. X    np->n_time = 0L;
  331. X    } else if (getstat(fd, &info) < 0)
  332. X    fatal("Can't getstat %s; error %02x", np->n_name, errno);
  333. X    else
  334. X    np->n_time = info.st_mod;
  335. X
  336. X    close(fd);
  337. X#endif
  338. X#ifdef os9
  339. X    struct sgtbuf   info;
  340. X    int         fd;
  341. X
  342. X
  343. X    if ((fd = open(np->n_name, 0)) < 0) {
  344. X    if (errno != E_PNNF)
  345. X        fatal("Can't open %s; error %02x", np->n_name, errno);
  346. X
  347. X    np->n_time = 0L;
  348. X    } else if (getmdate(fd, &info) < 0)
  349. X    fatal("Can't getstat %s; error %02x", np->n_name, errno);
  350. X    else
  351. X    np->n_time = cnvtime(&info);
  352. X
  353. X    close(fd);
  354. X#endif
  355. X#ifdef amiga
  356. X    struct FileInfoBlock *fib;
  357. X    struct FileLock *myLock;
  358. X    long ioErr;
  359. X
  360. X    fib = (struct FileInfoBlock *) malloc((unsigned) sizeof(struct FileInfoBlock));
  361. X    if ((myLock = Lock(np->n_name, ACCESS_READ)) == NULL) {
  362. X    if ((ioErr = IoErr()) != ERROR_OBJECT_NOT_FOUND)
  363. X        fatal("Can't Lock '%s'; error %3ld", np->n_name, ioErr);
  364. X    np->n_time = 0L;
  365. X    } else if (!Examine(myLock, fib)) {
  366. X    UnLock(myLock);
  367. X    fatal("Can't Examine '%s'; error %3ld", np->n_name, IoErr());
  368. X    } else {
  369. X    np->n_time = fib->fib_Date.ds_Tick/TICKS_PER_SECOND +
  370. X         60*fib->fib_Date.ds_Minute + 86400*fib->fib_Date.ds_Days;
  371. X    UnLock(myLock);
  372. X    }
  373. X    free((char *) fib);
  374. X#endif
  375. X
  376. X}
  377. X
  378. X#ifdef amiga
  379. Xchar *
  380. Xnametail(name)
  381. Xregister char *name;
  382. X{
  383. X    register char *tail;
  384. X
  385. X    if ((tail = index(name, ':')) == NULL)      /* strip device name */
  386. X    tail = name;
  387. X    if ((name = rindex(tail, '/')) == NULL)     /* strip directories */
  388. X    name = tail;
  389. X
  390. X    return name;
  391. X}
  392. X#endif
  393. X
  394. X
  395. X/*
  396. X *    Update the mod time of a file to now.
  397. X */
  398. Xvoid
  399. Xtouch(np)
  400. X    struct name    *np;
  401. X{
  402. X    char        c;
  403. X    int         fd;
  404. X
  405. X
  406. X    if (!domake || !silent)
  407. X    printf("    touch(%s)\n", np->n_name);
  408. X
  409. X    if (domake) {
  410. X#ifdef unix
  411. X    long        a[2];
  412. X
  413. X    a[0] = a[1] = time(0);
  414. X    if (utime(np->n_name, &a[0]) < 0)
  415. X        printf("%s: '%s' not touched - non-existant\n",
  416. X           myname, np->n_name);
  417. X#endif
  418. X#ifdef eon
  419. X    if ((fd = open(np->n_name, 0)) < 0)
  420. X        printf("%s: '%s' not touched - non-existant\n",
  421. X           myname, np->n_name);
  422. X    else {
  423. X        uread(fd, &c, 1, 0);
  424. X        uwrite(fd, &c, 1);
  425. X    }
  426. X    close(fd);
  427. X#endif
  428. X#ifdef os9
  429. X    /*
  430. X     * Strange that something almost as totally useless as this is easy
  431. X     * to do in os9!
  432. X     */
  433. X    if ((fd = open(np->n_name, S_IWRITE)) < 0)
  434. X        printf("%s: '%s' not touched - non-existant\n",
  435. X           myname, np->n_name);
  436. X    close(fd);
  437. X#endif
  438. X#ifdef amiga
  439. X    struct MsgPort *task;
  440. X    ULONG dateStamp[3];
  441. X    struct FileLock *lock, *plock;
  442. X    UBYTE *bcplstring;
  443. X
  444. X    if(!(bcplstring = (UBYTE *)AllocMem(64L, MEMF_PUBLIC)))
  445. X        fatal("Can't get 64 bytes for bcplstring");
  446. X    if(!(task=(struct MsgPort *)DeviceProc(np->n_name))) {
  447. X        printf("%s: can't get MsgPort for '%s'\n", myname, np->n_name);
  448. X        goto abort;
  449. X    }
  450. X    if(!(lock = Lock(np->n_name, SHARED_LOCK))) {
  451. X        printf("%s: '%s' not touched - non-existant\n",
  452. X            myname, np->n_name);
  453. X        goto abort;
  454. X    }
  455. X    plock = ParentDir(lock);
  456. X    UnLock(lock);
  457. X
  458. X    /* Strip pathnames first */
  459. X    strcpy((bcplstring + 1), nametail(np->n_name));
  460. X    *bcplstring = strlen(bcplstring + 1);
  461. X
  462. X    dos_packet(task, ACTION_SET_DATE, NULL, plock, (ULONG)bcplstring >> 2,
  463. X        (ULONG) DateStamp(dateStamp), 0L, 0L, 0L);
  464. X
  465. X    UnLock(plock);
  466. Xabort:
  467. X    FreeMem((void *) bcplstring, 64L);
  468. X#endif
  469. X    }
  470. X}
  471. X
  472. X/*
  473. X * Recursive routine to make a target.
  474. X */
  475. Xint
  476. Xmake(np, level)
  477. X    struct name    *np;
  478. X    int         level;
  479. X{
  480. X    register struct depend *dp;
  481. X    register struct line *lp;
  482. X    register struct depend *qdp;
  483. X    time_t        dtime = 1, time();
  484. X    bool        didsomething = 0;
  485. X    char *        basename  = (char *) 0;
  486. X    char *        inputname = (char *) 0;
  487. X
  488. X
  489. X    if (np->n_flag & N_DONE)
  490. X    return 0;
  491. X
  492. X    if (!np->n_time)
  493. X    modtime(np);            /* Gets modtime of this file  */
  494. X
  495. X    if (rules) {
  496. X    for (lp = np->n_line; lp; lp = lp->l_next)
  497. X        if (lp->l_cmd)
  498. X        break;
  499. X    if (!lp)
  500. X        dyndep(np, &basename, &inputname);
  501. X    }
  502. X    if (!(np->n_flag & N_TARG) && np->n_time == 0L)
  503. X    fatal("Don't know how to make %s", np->n_name);
  504. X
  505. X    for (qdp = (struct depend *) 0, lp = np->n_line; lp; lp = lp->l_next) {
  506. X    for (dp = lp->l_dep; dp; dp = dp->d_next) {
  507. X        make(dp->d_name, level + 1);
  508. X        if (np->n_time < dp->d_name->n_time)
  509. X        qdp = newdep(dp->d_name, qdp);
  510. X        dtime = max(dtime, dp->d_name->n_time);
  511. X    }
  512. X    if (!quest && (np->n_flag & N_DOUBLE) && (np->n_time < dtime)) {
  513. X        make1(np, lp, qdp, basename, inputname); /* free()'s qdp */
  514. X        dtime = 1;
  515. X        qdp = (struct depend *) 0;
  516. X        didsomething++;
  517. X    }
  518. X    }
  519. X
  520. X    np->n_flag |= N_DONE;
  521. X
  522. X    if (quest) {
  523. X    long        t;
  524. X
  525. X    t = np->n_time;
  526. X    time(&np->n_time);
  527. X    if (basename)
  528. X        free(basename);
  529. X
  530. X    return t < dtime;
  531. X    } else if (np->n_time < dtime && !(np->n_flag & N_DOUBLE)) {
  532. X    make1(np, (struct line *)0, qdp, basename, inputname); /* free()'s qdp */
  533. X    time(&np->n_time);
  534. X    } else if (level == 0 && !didsomething)
  535. X    printf("%s: '%s' is up to date\n", myname, np->n_name);
  536. X
  537. X    if (basename)
  538. X    free(basename);
  539. X
  540. X    return 0;
  541. X}
  542. X
  543. X
  544. Xmake1(np, lp, qdp, basename, inputname)
  545. X    register struct depend *qdp;
  546. X    struct line    *lp;
  547. X    struct name    *np;
  548. X    char       *basename;
  549. X    char       *inputname;
  550. X{
  551. X    register struct depend *dp;
  552. X
  553. X
  554. X    if (dotouch)
  555. X    touch(np);
  556. X    else {
  557. X    strcpy(str1, "");
  558. X    if (!basename)
  559. X        basename = str1;
  560. X    setmacro("*", basename);        /* $* = file */
  561. X    if (!inputname)
  562. X        inputname = str1;
  563. X    setmacro("<", inputname);       /* $< = path/file.c or file.c */
  564. X    for (dp = qdp; dp; dp = qdp) {
  565. X        if (strlen(str1))
  566. X        strcat(str1, " ");
  567. X        strcat(str1, dp->d_name->n_name);
  568. X        qdp = dp->d_next;
  569. X        free(dp);
  570. X    }
  571. X    setmacro("?", str1);            /* $? = file.c file1.h file2.h */
  572. X    setmacro("@", np->n_name);      /* $@ = file.o */
  573. X    if (lp)                 /* lp set if doing a :: rule */
  574. X        docmds1(np, lp);
  575. X    else
  576. X        docmds(np);
  577. X    }
  578. X}
  579. X#ifdef amiga
  580. X/*
  581. X * Replace the Aztec-provided time function with one which returns something
  582. X * easy to find and compare, namely the number of seconds since the Amiga's
  583. X * reference date.  This is the same thing returned by modtime() above.
  584. X */
  585. Xtime_t
  586. Xtime(v)
  587. X    time_t *v;
  588. X{
  589. X    long t[3];
  590. X
  591. X    DateStamp(t);
  592. X    t[0] = t[2]/TICKS_PER_SECOND + 60*t[1] + 86400*t[0];
  593. X    if (v)
  594. X    *v = t[0];
  595. X    return t[0];
  596. X}
  597. X#endif
  598. END_OF_FILE
  599. if test 11870 -ne `wc -c <'make.c'`; then
  600.     echo shar: \"'make.c'\" unpacked with wrong size!
  601. fi
  602. # end of 'make.c'
  603. fi
  604. echo shar: End of archive 2 \(of 2\).
  605. cp /dev/null ark2isdone
  606. MISSING=""
  607. for I in 1 2 ; do
  608.     if test ! -f ark${I}isdone ; then
  609.     MISSING="${MISSING} ${I}"
  610.     fi
  611. done
  612. if test "${MISSING}" = "" ; then
  613.     echo You have unpacked both archives.
  614.     rm -f ark[1-9]isdone
  615. else
  616.     echo You still need to unpack the following archives:
  617.     echo "        " ${MISSING}
  618. fi
  619. ##  End of shell archive.
  620. exit 0
  621. -- 
  622. Submissions to comp.sources.amiga and comp.binaries.amiga should be sent to:
  623.     amiga@cs.odu.edu    
  624. or    amiga@xanth.cs.odu.edu    ( obsolescent mailers may need this address )
  625. or    ...!uunet!xanth!amiga    ( very obsolescent mailers need this address )
  626.  
  627. Comments, questions, and suggestions s should be addressed to ``amiga-request''
  628. (only use ``amiga'' for submissions) at the above addresses.
  629.